package com.ytjj.qmyx.mall.service.impl.taoxingou;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import com.github.binarywang.wxpay.v3.util.SignUtils;
import com.github.wxpay.sdk.WXPayUtil;
import com.ytjj.common.constants.CopyWriterConstant;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.utils.CopyWriterConfigUtil;
import com.ytjj.qmyx.mall.mapper.OrdersDao;
import com.ytjj.qmyx.mall.mapper.OrdersPayMapper;
import com.ytjj.qmyx.mall.mapper.PayConfigMapper;
import com.ytjj.qmyx.mall.model.OrdersPay;
import com.ytjj.qmyx.mall.model.OrdersPayExample;
import com.ytjj.qmyx.mall.model.PayConfig;
import com.ytjj.qmyx.mall.model.dto.WxPayDto;
import com.ytjj.qmyx.mall.service.WxService;
import com.ytjj.qmyx.mall.utils.WxPayServiceUtil;
import com.ytjj.qmyx.mall.utils.WxpayV3Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.util.*;

@Service("H5-ISV-JSAPI-TXG")
@Slf4j
public class WxISVH5TxgJsApiServiceImpl implements WxService<WxPayDto> {

    @Resource
    private OrdersDao ordersDao;
    @Resource
    private OrdersPayMapper ordersPayMapper;
    @Resource
    private PayConfigMapper payConfigMapper;

    @Resource
    private CopyWriterConfigUtil copyWriterConfigUtil;
    public static final String COMPANY = "taoxingou";
    public static final String TYPE = "H5";
    public static final String TRADE_TYPE = "JSAPI";

    @Override
    public Map<String, String> doUnifiedOrder(WxPayDto wxPayDto) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(COMPANY, TYPE, TRADE_TYPE);

        // 构造请求数据
        JSONObject reqJSON = WxPayServiceUtil.buildV3OrderRequest(wxPayDto, payConfig);
        JSONObject payer = new JSONObject();
        payer.put("sub_openid", wxPayDto.getOpenid());
        reqJSON.put("payer", payer);

        WxPayService wxPayService=WxPayServiceUtil.getWxPayService(payConfig);
        wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI);
        wxPayService.getConfig().setPrivateKeyPath(payConfig.getPrivateKeyPath());
        wxPayService.getConfig().setCertSerialNo(payConfig.getCertSerialNo());
        wxPayService.getConfig().setApiV3Key(payConfig.getWxKey());
        String reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
        try {
            // 调起上游接口：
            // 1. 如果抛异常，则订单状态为： 生成状态，此时没有查单处理操作。 订单将超时关闭
            // 2. 接口调用成功， 后续异常需进行捕捉， 如果 逻辑代码出现异常则需要走完正常流程，此时订单状态为： 支付中， 需要查单处理。
            JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
            log.info("微信返回 {}",resJSON);
            Map<String, String> payInfo = new HashMap<>(); // 如果用JsonObject会出现签名错误
            String packageStr = ""+ resJSON.get("package");
            String timestamp = System.currentTimeMillis() / 1000 + "";
            String nonceStr = WXPayUtil.generateNonceStr();
            payInfo.put("appId", payConfig.getSubAppId());
            payInfo.put("timeStamp", timestamp);
            payInfo.put("nonceStr", nonceStr);
            payInfo.put("package", packageStr);
            payInfo.put("signType", "RSA");

            String beforeSign = String.format("%s\n%s\n%s\n%s\n", payConfig.getSubAppId(), timestamp, nonceStr, packageStr);
            payInfo.put("sign", SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(wxPayService.getConfig().getPrivateKeyPath()))));

            payInfo.put("payConfigId", String.valueOf(payConfig.getId()));
            return payInfo;
        }catch (Exception e) {
            throw new Exception("下单失败");
        }
    }

    @Override
    public Map<String, String> doUnifiedRechargeOrder(WxPayDto wxPayDto) throws Exception {
        return null;
    }


    @Override
    public Map<String, String> wxOrderQuery(String resOrderNo) throws Exception {
        PayConfig payConfig = ordersDao.getPayConfigByCompany(COMPANY, TYPE, TRADE_TYPE);

        WxPayService wxPayService = WxPayServiceUtil.getWxPayService(payConfig);
        wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI);
        wxPayService.getConfig().setPrivateKeyPath(payConfig.getPrivateKeyPath());
        wxPayService.getConfig().setCertSerialNo(payConfig.getCertSerialNo());
        wxPayService.getConfig().setApiV3Key(payConfig.getWxKey());
        String reqUrl = String.format("/v3/pay/partner/transactions/out-trade-no/%s", resOrderNo);
        String query = String.format("?sp_mchid=%s&sub_mchid=%s", wxPayService.getConfig().getMchId(), payConfig.getSubMchId());

        JSONObject resultJSON = WxpayV3Util.queryOrderV3(reqUrl + query, wxPayService.getConfig());

        log.info("微信H5公众号支付状态查询请求 订单号：{},query: {}", resOrderNo, resultJSON);
        //使用官方API请求预付订单
        Map<String, String> response = new HashMap<>();
        Set<String> set= resultJSON.keySet();
        Iterator it = set.iterator();
        // 遍历jsonObject数据，添加到Map对象
        while (it.hasNext()){
            String key = String.valueOf(it.next());
            response.put(key, resultJSON.getString(key));
        }
        log.info("微信H5公众号支付状态查询响应 订单号：{},response: {}", resOrderNo, JSONObject.toJSONString(response));
        return response;
    }

    @Override
    public Map<String, String> wxPhoneChargesQuery(String resOrderNo) {
        return null;
    }

    @Override
    public Map refundOrders(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
//        PayConfig payConfig = ordersDao.getPayConfigByCompany(COMPANY, TYPE, TRADE_TYPE);
        OrdersPayExample ordersPayExample = new OrdersPayExample();
        ordersPayExample.createCriteria().andResOrderNoEqualTo(outTradeNo).andPayTypeEqualTo(new Byte("2"));
        ordersPayExample.setOrderByClause("id desc");
        List<OrdersPay> ordersPays = ordersPayMapper.selectByExample(ordersPayExample);
        PayConfig payConfig = null;
        if (!CollectionUtils.isEmpty(ordersPays)) {
            payConfig = payConfigMapper.selectByPrimaryKey(ordersPays.get(0).getPayConfigId());
        }
        if (null == payConfig) {
            throw new ApiException("退款失败，请联系管理员！！！");
        }

        JSONObject reqJSON = new JSONObject();
        reqJSON.put("out_trade_no", outTradeNo);   // 订单号
        reqJSON.put("out_refund_no", outRefundNo); // 退款订单号
        reqJSON.put("reason",refundDesc);
        JSONObject amountJson = new JSONObject();
        amountJson.put("refund", refundFee);// 退款金额
        amountJson.put("total", totalFee);// 订单总金额
        amountJson.put("currency", "CNY");// 币种
        reqJSON.put("amount", amountJson);
        WxPayService wxPayService = WxPayServiceUtil.getWxPayService(payConfig);
        wxPayService.getConfig().setKeyPath(payConfig.getCertPath());// 证书路径
        wxPayService.getConfig().setPrivateKeyPath(payConfig.getPrivateKeyPath());
        wxPayService.getConfig().setCertSerialNo(payConfig.getCertSerialNo());
        wxPayService.getConfig().setApiV3Key(payConfig.getWxKey());
        reqJSON.put("sub_mchid", payConfig.getSubMchId());
        JSONObject resultJSON = WxpayV3Util.refundV3(reqJSON, wxPayService.getConfig());
        log.info("退款结果{}",resultJSON.toJSONString());
        String status = resultJSON.getString("status");
        Map<String, String> response = new HashMap<>();
        response.put("status",status);
        if("SUCCESS".equals(status)){ // 退款成功
            String refundId = resultJSON.getString("refund_id");
            response.put("out_refund_no",resultJSON.getString("out_refund_no"));
            response.put("refund_id",resultJSON.getString("refund_id"));
            response.put("out_trade_no",resultJSON.getString("out_trade_no"));
        }else if ("PROCESSING".equals(status)){ // 退款处理中
            String refundId = resultJSON.getString("refund_id");
            response.put("out_refund_no",resultJSON.getString("out_refund_no"));
            response.put("refund_id",resultJSON.getString("refund_id"));
            response.put("out_trade_no",resultJSON.getString("out_trade_no"));
        }else{
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.REFUND_FAILED));
        }
        log.info("微信发起退款：response:{}",JSONObject.toJSONString(response));
        return response;
    }

    /**
     * 话费充值退款
     * @param outTradeNo
     * @param outRefundNo
     * @param totalFee
     * @param refundFee
     * @param refundDesc
     * @return
     * @throws Exception
     */
    @Override
    public Map refundRecharge(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
        return null;
    }

    public static void main(String[] args) throws Exception {

    }

}
